home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Arashi 1.1 / Game Source / mtz / mtz src / new mods < prev    next >
Encoding:
Text File  |  1993-02-07  |  30.2 KB  |  1,125 lines  |  [TEXT/KAHL]

  1. New changes which I want to add to a 1.1 version....
  2.  
  3.  
  4. Summary
  5. -------
  6. 1) Fuseballs have different scoring attributes depending upon how they
  7. are killed.
  8.  
  9. 2) due to the variable scoring, show the score above the dead fuseball for a short 
  10. interval. 
  11.  
  12. 3)Wanted to set up a way for players to be able to pass thru fuseballs that were on
  13. the edge.
  14.  
  15. 4) changed MAXSAVED value in VA.h to 1000 and MAXCRACKS value in STCrack.c to 60.
  16.  
  17. 5) Wanted to make the second superzap a little smarter, ie  more likely to kill 
  18. the most dangerous enemy on the board.
  19.  
  20. 6) Added the test of Color Quickdraw to GameLoop.c in StormStart()
  21.  
  22. 7) Wanted to prevent someone with System earlier than 6.0.7. from checking radio
  23. box.
  24.  
  25. 8) After the last green level, the green levels should repeat in random sequence.
  26.  
  27. 9) Allow players to slip under a rotating pulsar on the edge.
  28.  
  29. 10) Changed CLOT which was loaded during the level select presentation for the
  30. invis levels.
  31.  
  32. 11) Added message "Watch out for Spikes" to certain early levels.  
  33.  
  34. 12) To prevent the level number and enemy counts from also being invisible
  35. on the invis waves, I flagged for lvColor==5 and changed the VA.color = BG1
  36. in GameLoop.c and GridTest.c
  37.  
  38. 13) Added a check box to allow user to choose whether or not to show floating fuseball
  39. scores.
  40.  
  41. 14) Modified pulsar behavior to more mimick the arcade behavior.
  42.  
  43. 15) Added a FlyOut routine to STFlyThru.c.
  44.  
  45. 16) Changed so a zapped Tanker does not split.
  46.  
  47. 17) Added a second high score list for Practice mode. 
  48.  
  49. 18) Added "Save game" and "Load game" options to the Pause dialog. 
  50.  
  51. 19) Added next highest score on high score list to display in upper right corner.
  52.  
  53. 20) on Doomsday levels (after 96) if the player dies, a new level (random) is selected.
  54.  
  55. 21) Changed the floating scores so they would not be called if a superzap was used.
  56.  
  57. 22) Fixed free life flash bug.
  58.  
  59. 23) Set a max of 5 lives (plus active life)
  60.  
  61. 24) Added "Superzapper Recharge" message to fly-in routine.
  62.  
  63. 25) Bug fix for several things related to if the starting level has been
  64. completed.
  65.  
  66. 26) changed fuseball behavior.
  67.  
  68. 27) Changed extra life sound and flash related to clearing first level and 
  69. starting bonus.
  70.  
  71. 28) Another fix for GamePause.
  72.  
  73. 29) Changed Levelselect to include saved game.  Added extra save game so each
  74. play mode has game save.
  75.  
  76. 30) Another attempt to fix the occassional errant zoomer box on the high scores.
  77.  
  78. --------
  79. 1) Fuseballs have different scoring attributes depending upon how they
  80. are killed.
  81.  
  82. A fuseball hit in the lower 1/3 of the lane is worth 750, in the middle 500,
  83. up top 250
  84.  
  85. So near the end of UpdateFuseballs()
  86.  
  87. {    if(ShotHitTest(fbp->lane,l))
  88.                     {    fbp->activeflag=0;
  89.                         NumBalls--;
  90.                         ThisLevel.fuCount--;
  91.                         ThisLevel.totalCount--;
  92.                         
  93.                         /* have different score for Fuseballs depending upon     */
  94.                         /* how deeply they are killed (mz)     */
  95.                         
  96.                         if ( (DEPTH>l) && ( l >= (int)(DEPTH*2/3) ) )
  97.                         {        /* bottom 1/3 */
  98.                             IncreaseScore(ThisLevel.fuBullseye*1.5);
  99.                             AddFLScore(x,y,ThisLevel.fuBullseye*1.5);
  100.                         }
  101.                         
  102.                         else if ( ((DEPTH*2/3)>l) && (l>=(int)(DEPTH/3)) )
  103.                         {        /* middle 1/3 */
  104.                             IncreaseScore((ThisLevel.fuBullseye));
  105.                             AddFLScore(x,y,(ThisLevel.fuBullseye));
  106.                         }
  107.                         
  108.                         else
  109.                         {        /* upper 1/3 */
  110.                             IncreaseScore(ThisLevel.fuBullseye/2);
  111.                             AddFLScore(x,y,ThisLevel.fuBullseye/2);
  112.                         }
  113.                         
  114.                         BlowFuseBall(x,y,ww.unitlen[l],fbp->rotation);
  115.                         PlayB(Blow,11);
  116.                     }
  117.                 }
  118.  
  119.                 
  120. 2) due to the variable scoring, show the score above the dead fuseball for a short 
  121. interval.  From Fuseball.c this is done with a call to AddFLScore.  Also
  122. at the top of STFuseball.c you must include
  123.  
  124. #include "STFloatingScores.h"
  125.  
  126. the file STFloatingScores.c (included with this file) handles the floating scores.  
  127. Appropriate lines are added to STInterface.c to alloc,init, an update the structure 
  128. for floating scores.
  129.  
  130. Also wanted to insure that no scores were left up during FlyThru so I added
  131. to FlyThruLoop()
  132.  
  133.     for(i=0;i<TANKTYPES;i++)
  134.     {    ThisLevel.tk[i].count=0;
  135.     }
  136.     if(PlayOptions->showfscores)
  137.         UpdateFloatingScores();                /* kill off any floating scores remaining */
  138.     if (ThisLevel.spProb  && ThisLevel.lvNumber <=8)
  139.         DoWatchSpikesMsg();
  140.  
  141. 3)Wanted to set up a way for players to be able to pass thru fuseballs that were on
  142. the edge.  On the real TEMPEST you could pass thru a fuseball that was on a vertex
  143. exactly.  The closest and by easiest change I saw to make was to prevent the
  144. fuseMask from being added to the lanestat if the fuseball was sufficiently in
  145. the outer sublanes.  Right now I have set this as the upper and lower 4 sublanes,
  146. allowing fully 1/16 th of the lane to be safe for a player.  To do this, modify the
  147. test in UpdateFuseballs()
  148.  
  149. /* Test for fuseball on edge of lane (fbp->lane)*/
  150.                 /* want to add test to allow player to pass thru fuseball */
  151.                 /* as it changes lanes */
  152.                 /* So test to see if the fuseball is in the outer 16 sublanes */
  153.                 /* if it is, then let the player pass thru by not adding the fusemask */
  154.                 /* to the lanstat (mz) */
  155.                 /* eg 
  156.                 sublanes  0...3 4............................251 252....255 
  157.                            ^^^                 ^^^^                    ^^
  158.                            safe                    dead                  safe   (mz) N*/
  159.                            
  160.                 if(    (l<FUSEDANGERLEVEL) && 
  161.                     (fbp->sublane>(LANEDIVISIONS/16)) && 
  162.                     (fbp->sublane<(LANEDIVISIONS-LANEDIVISIONS/64)) )
  163.                 {    Hero.lanestat[fbp->lane] |= FuseMask;
  164.                 } 
  165.         
  166. 4) changed MAXSAVED value in VA.h to 1000 and MAXCRACKS value in STCrack.c to 60.
  167.  
  168. 5) Wanted to make the second superzap a little smarter, ie  more likely to kill 
  169. the most dangerous enemy on the board.  The simplest thing I saw to do was to
  170. change the order of the Updates() so that Fuseballs came first the, puslars, then 
  171. flippers.  Now a fuseball is most likely to be killed.  So in STInterface.c
  172. in STUpdate()
  173.  
  174.     UpdatePlayer();
  175.     UpdateFuseBalls(); /* */
  176.     UpdatePulsars();
  177.     UpdateFlippers(); /* */
  178.     UpdateShots();
  179.     UpdateSpikes();
  180.     UpdateTankers();
  181.     UpdateCracks();
  182.     UpdateFloatingScores();    /* mz */
  183.     
  184. 6) Added the test of Color Quickdraw to GameLoop.c in StormStart()
  185.  
  186. #include <GestaltEqu.h>
  187. #include <OSUtils.h>
  188. #include <Types.h>
  189.     
  190.     long            myFeature;
  191.     
  192.     DoInits();
  193.     
  194.     /* Now do check for Color Quickdraw. Any version above simple 8 bit will do. */
  195.     if(Gestalt(gestaltQuickdrawVersion, &myFeature))
  196.         ExitToShell();
  197.     if (myFeature < gestalt8BitQD)
  198.     {
  199.         Alert(201,0);
  200.         ExitToShell();
  201.     }
  202.  
  203. 7) Wanted to prevent someone with System earlier than 6.0.7. from checking radio
  204. box.  So I changed PlayOptions.c 
  205.  
  206. #include    <GestaltEqu.h>
  207.  
  208. void    DataToRadioButtons()
  209. {
  210.     int        i;
  211.     long            myFeature;
  212.     
  213.     
  214.     /* Now do check for System Version 6.0.7 for sound */
  215.     if(Gestalt(gestaltSystemVersion, &myFeature))
  216.         ExitToShell();
  217.     if (myFeature < 0x0607)
  218.     {
  219.         PlayOptions->sys607Sound = 0;
  220.         SetItemEnable(StartDialog,Sys607Sound,255);
  221.     }
  222.     .
  223.     .
  224.     .
  225.     
  226. 8) After the last green level, the green levels should repeat in random sequence.
  227. To do this I changes STResource.c.  The lvNext in LEVL 223 (level 96) points
  228. to a non-existant LEVL 224.  Flag for that, and go into random levels.
  229.  
  230. #define RANDOMLEVELS 224        /* if it loops around */
  231. #define STARTGREEN 208
  232.  
  233. void    STLoadLevel()
  234. {
  235.     register    int                    i;
  236.     register    EditorLevelType        *edp,**edh;
  237.                 int                    randGreenLevel;
  238.     static        int                    highLvNum;
  239.     
  240.     
  241.     /* Check to see if last green level completed (mz) */
  242.     if (ThisLevel.lvNext == RANDOMLEVELS)
  243.     {
  244.         ThisLevel.lvType = 4;
  245.         highLvNum = 97;
  246.     }
  247.         
  248.     switch(ThisLevel.lvType)
  249.     .
  250.     .
  251.     .
  252.     
  253.     case 4: 
  254.             randGreenLevel = STARTGREEN + ((unsigned int)(Random()) % 16);
  255.             ThisLevel= **(LevelInfo **)GetResource('LEVL',randGreenLevel);
  256.             ThisLevel.lvType = 4;
  257.             ThisLevel.lvNumber = highLvNum;
  258.             highLvNum++;
  259.             break;
  260.             
  261. Also had to add a lvType reset measure in GameLoop.c so the next game would
  262. not start with the random level flag set.
  263.  
  264. long    PlayGame(HighScore,Options)
  265. long    HighScore;
  266. int        Options;
  267. {
  268.     int        i;
  269.     
  270.     Hero.score = -1;
  271.     i=DoLevelSelect(&highestLastLevel);            /* transfer variable (mz) */
  272.     ThisLevel.lvType=0;                            /* reset if from random (mz) */
  273.     if(i>=0)
  274.     {    VA.FrameSpeed=3;
  275.         ThisLevel.lvNext=i;
  276.         GameLoop(Options);
  277.     }
  278.             
  279. 9) Allow players to slip under a rotating pulsar on the edge.  Modify STPulsar.c
  280. UpdatePulsars()
  281.  
  282.     if(!VA.Late)                /*    Is there time to draw something?    */
  283.     {    if(pulsarp->mirror)        /*    Is the pulsar mirrored?            */
  284.             DrawPulsar(x+dx,y+dy,-dx,-dy,PulsarPower);
  285.         else
  286.             DrawPulsar(x,y,dx,dy,PulsarPower);
  287.     }
  288.  
  289.     /*    Notify the player record if a pulsar is on the edge.            */
  290. /*    if(pulsarp->level.i==0)
  291.     {    Hero.segmstat[pulsarp->vertex] |= PulsMask;
  292.     } */ /* Allow player to slip under rotating pulsar */
  293.     
  294. 10) Changed CLOT which was loaded during the level select presentation for the
  295. invis levels.  Added a new CLOT (#5+128=133) and changed STLevelSelect.c 
  296.  
  297. int        CreateStable(stable,highestLastLevel)
  298. .
  299. .
  300. .
  301. colorresource = (*LInfo)->lvColor;
  302. if (colorresource == 5)                /* if invis field color use grey shade     */
  303.     colorresource = (*LInfo)->lvColor + 128;    /* for invisi levels (mz)     */
  304.                         
  305. Causes invis levels to appear as white during level select.
  306.  
  307. Also changed CreateFit() in Gridtest.c for the same purpose
  308.  
  309.     if (ThisLevel.lvColor != 5)            /* Use alternate grey for invis levels (mz) */
  310.         OpenStars(GetResource('CLOT',ThisLevel.lvColor));
  311.     else
  312.         OpenStars(GetResource('CLOT',ThisLevel.lvColor + 128));
  313.  
  314. the player will see a faint grey during "fly-in".
  315.  
  316. 11) Added message "Watch out for Spikes" to certain early levels.  Did this by adding
  317. to the file STFlythru.c.  Add the routine
  318.  
  319. void DoWatchSpikesMsg()
  320. {
  321.     /* This next section will add the message                 */
  322.     /* "Watch out for Spikes" to levels 3-8 so the new         */
  323.     /* player will know to avoid them. (mz)                 */
  324.     
  325.     unsigned char    *text=(void *)"\pAvoid Spikes ";
  326.     long            targetTicks;
  327.     
  328.     VAMoveTo(VA.frame.right/3,VA.frame.bottom/2 - 2);
  329.     VA.segmscale= VA.segmscale;
  330.     if(VA.segmscale <=1) VA.segmscale=2;
  331.     VA.color=BG1;
  332.     VADrawText((char *)text,1,12);
  333.     
  334.     targetTicks = Ticks + 120;
  335.     /* Now delay for 2 secs.  Update Player and Shots, then erase msg and return */
  336.     while(Ticks <= targetTicks)
  337.     {
  338.         GameEvent();
  339.         UpdatePlayer();
  340.         UpdateShots();
  341.         UpdateCracks();
  342.         VAStep();
  343.     }
  344.     VAMoveTo(VA.frame.right/3,VA.frame.bottom/2 - 2);
  345.     text=(void *)"\p             ";
  346.     VADrawText((char *)text,1,12);
  347. }
  348. Then in FlyThruLoop() I added a call to it if it was the right level...
  349.  
  350. for(i=0;i<TANKTYPES;i++)
  351.     {    ThisLevel.tk[i].count=0;
  352.     }
  353.     
  354.     if (ThisLevel.spProb  && ThisLevel.lvNumber <=8 && Options == NormalPlay)
  355.         DoWatchSpikesMsg();;
  356.         
  357. Note that all of the enemies are dead, so there is no way for the player to die and
  358. leave the message on the screen.
  359.  
  360. 12) To prevent the level number and enemy counts from also being invisible
  361. on the invis waves, I flagged for lvColor==5 and changed the VA.color = BG1
  362. in GameLoop.c and GridTest.c
  363.  
  364. in CreateFit()
  365.  
  366.     k=VA.color;
  367.     VA.color=BG2;
  368.     if (ThisLevel.lvColor == 5)        /* check for invis BG2 on ivis waves (mz) */
  369.         VA.Color=BG1;
  370.     VADrawNumber(ThisLevel.lvNumber,VA.frame.right/2-VA.segmscale-3,VA.segmscale*2+4);
  371.     VA.color=k;
  372.     
  373. in GameLoop()
  374.  
  375.             if (!(PlayOptions->restart == 0))    /* only show count if Practice mode */
  376.             {
  377.                 if (ThisLevel.lvColor == 5)        /* check for invis lvl where BG2 is */
  378.                     VA.color=BG1;                /* also invis. (mz)                 */
  379.                 VADrawPadNumber(ThisLevel.totalCount,VA.frame.right-10,40,3);
  380.                 VADrawPadNumber(ThisLevel.edgeCount,VA.frame.right-10,60,3);
  381.                 VA.color = BG2;
  382.             }
  383.  
  384. in STFlyThru.c
  385. MapFlycolors()
  386.  
  387. ...
  388. FlyColors=GetResource('CLOT',ThisLevel.lvColor);
  389.     if (ThisLevel.lcColor == 5)
  390.         FlyColors=GetResource('CLOT',ThisLevel.lvColor + 128);
  391.     HandToHand(&FlyColors);
  392.     colp = (ColorSpec *)*FlyColors;
  393.     ....
  394.     
  395. 13) Added a check box to allow user to choose whether or not to show floating fuseball
  396. scores.
  397.  
  398. Added to PlayOptions.h
  399.  
  400. typedef    struct
  401. {
  402.     int        absMoveFlag;
  403.     int        mouseSensitivity;
  404.     int        rotationType;
  405.     int        blankUnused;
  406.     int        monochrome;
  407.     int        soundOff;
  408.     int        noLoudSounds;
  409.     int        verticalGame;
  410.     int        sys607Sound;
  411.     int        restart;                    /* (mz) how to restart */
  412.     int        showfscores;
  413. }    PlayOptionsRecord;
  414.  
  415. in DataToRadioButtons()
  416. SetStartItem(ShowFuseScores,    PlayOptions->showfscores);
  417.  
  418. in DoStartupDialog(item)
  419. case ShowFuseScores:    PlayOptions->showfscores= !PlayOptions->showfscores;break;            
  420.         
  421. in STInterface
  422. if(PlayOptions->showfscores)
  423.         UpdateFloatingScores();    /* mz */
  424.         
  425. in STFuseball.c
  426.                         if ( (DEPTH>l) && ( l >= (int)(DEPTH*2/3) ) )
  427.                         {        /* bottom 1/3 */
  428.                             IncreaseScore(ThisLevel.fuBullseye*1.5);
  429.                             if(PlayOptions->showfscores)
  430.                                 AddFLScore(x,y,ThisLevel.fuBullseye*1.5);
  431.                         }
  432.                         
  433.                         else if ( ((DEPTH*2/3)>l) && (l>=(int)(DEPTH/3)) )
  434.                         {        /* middle 1/3 */
  435.                             IncreaseScore((ThisLevel.fuBullseye));
  436.                             if(PlayOptions->showfscores)
  437.                                 AddFLScore(x,y,(ThisLevel.fuBullseye));
  438.                         }
  439.                         
  440.                         else
  441.                         {        /* upper 1/3 */
  442.                             IncreaseScore(ThisLevel.fuBullseye/2);
  443.                             if(PlayOptions->showfscores)
  444.                                 AddFLScore(x,y,ThisLevel.fuBullseye/2);
  445.                         }
  446.     
  447. 14) Modified pulsar behavior to more mimick the arcade behavior.  For first 25%
  448. and last 25% of pulsar->counter, then lane Mask is not set, allowing a player
  449. to move over it and shoot.  Change was made to DoPulsing() in STPulsar.c
  450.  
  451.     if(pulsarp->pulscounter)
  452.     {    if(ThisLevel.puPulsDepth > pulsarp->level.i)
  453.         {    pulsarp->pulscounter--;
  454.             /* change in pulsar behavior so it waits then pulses, then waits */
  455.             /* in each lane. (mz) */
  456.             if( (pulsarp->pulscounter < (int)(PULSINGTIME*.75)) &&
  457.                     (pulsarp->pulscounter > (int)(PULSINGTIME*.25)))
  458.                 Hero.lanestat[pulsarp->lane] |= PulsMask;
  459.             if(PulsarPower>=13 && pulsarp->pulscounter<NERVOUSNESS)
  460.             
  461. 15) Added a FlyOut routine to STFlyThru.c.  This is called after a player
  462. loses the last life during NormalPlay and not from a player hitting 'q' to quit.
  463. Added the routine and added to GameLoop.c
  464. int    FinalDeathMode=1;
  465.  
  466.                         switch(Event.message & 0xFF)
  467.                         {    case 'q':
  468.                             case 'Q':
  469.                             case 27:
  470.                             case 13:    Hero.state=HeroDead;
  471.                                         Hero.lives=0;                
  472.                                         int    FinalDeathMode=1;
  473.                                         break;
  474.                             case ' ':    /* Handled in player routine    */
  475.                                                                     break;
  476.                                                                     
  477.                             .
  478.                             .
  479.                             .
  480.     } while(Hero.lives>0 || Hero.state != HeroDead);
  481.     
  482.     if (FinalDeathMode && Options == NormalPlay)
  483.         STFlyOutLoop();            /* test */
  484.     
  485.     FinalDeathMode = 1;
  486.     
  487. 16) Changed so a zapped Tanker does not split.  In STShots.c
  488.  
  489. in ShotHitTest() I made it return a -2 is zapping
  490.  
  491.     if(Hero.superzapping)
  492.     {    if(Hero.superzapping==2)    /*    Single enemy zap.    */
  493.             Hero.superzapping=0;
  494.         return -2;                    /* mz */
  495.     }
  496.     
  497. Then in UpdateTanker(), change to check for a zap.  If a shot still split.
  498.  
  499.         if(zap = ShotHitTest(thetank->lane,thetank->level.i)) /* mz */
  500.         {    PlayB(Zroom,11);
  501.             IncreaseScore(ThisLevel.tk[thetank->tanktype].points);
  502.             if (zap != -2)
  503.                 split=1;            /* mz */
  504.         }
  505.         else
  506.             {
  507.                 ThisLevel.totalCount--;
  508.                 thetank->state=inactive;
  509.                 ActiveTankers--;
  510.                 ActiveTypes[thetank->tanktype]--;
  511.             }
  512.             
  513. 17) Added a second high score list for Practice mode.  Used rsrc 129 for the list, and
  514. added appropriate other TEXT strings.  Changes wre made in HighScores.c and highmain.c.
  515.  
  516. in highscores.c...
  517.  
  518. Highscores(score)
  519. long    score;
  520. {
  521.     int    i,ranking,ranky;
  522.     Handle    ScoreHand;
  523.  
  524.     VASetColors(GetResource('CLOT',1002));
  525.         
  526.     
  527.     if (PlayOptions->restart == 0)
  528.         ScoreHand=GetResource('SCOR',128);
  529.         
  530.  
  531. void WriteCongrats()
  532. {
  533.     int        x,y,i;
  534.     int     len;
  535.     Handle    TextHand;
  536.     char    *str,*Text;
  537.     
  538.     if (PlayOptions->restart == 0)
  539.     {
  540.         TextHand=GetResource('TEXT',1000);
  541.         HLock(TextHand);
  542.         x = VA.frame.right/3.5;
  543.         y = VA.frame.bottom/8;
  544.     }
  545.     else
  546.     {
  547.         TextHand=GetResource('TEXT',1010);
  548.         HLock(TextHand);
  549.         x = VA.frame.right/4;
  550.         y = VA.frame.bottom/8;
  551.     }
  552.     
  553.     
  554. void WriteCongrats2()
  555. {
  556.     int        x,y,i;
  557.     int     len;
  558.     Handle    TextHand;
  559.     char    *str,*Text;
  560.     
  561.     if (PlayOptions->restart == 0)
  562.     {
  563.         TextHand=GetResource('TEXT',132);
  564.         HLock(TextHand);
  565.         x = VA.frame.right/3.5;
  566.         y = VA.frame.bottom/8;
  567.     }
  568.     else
  569.     {
  570.         TextHand=GetResource('TEXT',136);
  571.         HLock(TextHand);
  572.         x = VA.frame.right/4;
  573.         y = VA.frame.bottom/8;
  574.     }
  575.     
  576. in Highmain.c
  577.  
  578. HighMain() 
  579. {
  580.     Handle    ScoreHand;
  581.         
  582.     /* read scores from resources 
  583.     ScoreHand=GetResource('SCOR',128); */
  584.     if (PlayOptions->restart == 0)
  585.         ScoreHand=GetResource('SCOR',128);
  586.     else 
  587.         ScoreHand=GetResource('SCOR',129);
  588.     HLock(ScoreHand);
  589.     
  590. DisplayScores()
  591. {
  592.     char    Pstring[255];
  593.     int        i,x,y,len;
  594.     char    *str;
  595.     Handle    TextHand;
  596.     char    *Text;
  597.  
  598.     if (PlayOptions->restart == 0)
  599.         TextHand=GetResource('TEXT',1001);
  600.     else 
  601.         TextHand=GetResource('TEXT',1011);
  602.     
  603.     HLock(TextHand);
  604.     
  605. 18) Added "Save game" and "Load game" options to the Pause dialog.  
  606.  
  607. Modified GamePause.c
  608.  
  609. #include "PlayOptions.h"
  610. extern    Player            Hero;        /* mz */
  611.  
  612. typedef struct{
  613.         int        lvnum;
  614.         int        lvType;
  615.         long    score;
  616.         int        lives;
  617.         long    freelives;
  618.         int        ShowFuseScores;
  619.         int        RestartMode;
  620.         int        Flags;
  621.         int        NumZaps;
  622.         } **GameRecHand, GameRec;
  623.         
  624.         
  625. in GamePause(cleanup)        
  626.         int            GameLoaded = 0;    /* mz */
  627.         int            i;    /* mz */
  628.         
  629.         
  630.                     switch(ItemHit)
  631.                     {    case RotateRightRadio:
  632.                         .
  633.                         .
  634.                         .
  635.                         
  636.                         case SaveGame:
  637.                             {    GameRecHand    TheGameHand;
  638.                                 GameRec        TheGame;
  639.                                 
  640.                                 TheGameHand = GetResource('SVGM',128);
  641.                                 (**TheGameHand).lvnum = ThisLevel.lvNumber; 
  642.                                 (**TheGameHand).lvType = ThisLevel.lvType;
  643.                                 (**TheGameHand).lives = Hero.lives;
  644.                                 (**TheGameHand).score = Hero.score;
  645.                                 (**TheGameHand).freelives = Hero.freeLives;
  646.                                 (**TheGameHand).ShowFuseScores = PlayOptions->showfscores;
  647.                                 (**TheGameHand).RestartMode = PlayOptions ->restart;
  648.                                 (**TheGameHand).Flags = Hero.Flags;
  649.                                 (**TheGameHand).NumZaps = ThisLevel.plSuperZaps;
  650.                                 ChangedResource(TheGameHand);
  651.                                 WriteResource(TheGameHand);
  652.                                 ReleaseResource(TheGameHand);
  653.                                 Alert(500,0); 
  654.                             }
  655.                             break;
  656.                         case LoadGame:
  657.                             {    GameRecHand    TheGameHand;
  658.                                 GameRec    TheGame;
  659.                                 
  660.                                 TheGameHand = GetResource('SVGM',128);
  661.                                 
  662.                                 PlayOptions->showfscores = (**TheGameHand).ShowFuseScores;
  663.                                 PlayOptions ->restart = (**TheGameHand).RestartMode;
  664.                                 
  665.                                 ThisLevel.lvNext = 127 + (**TheGameHand).lvnum;
  666.                                 ThisLevel.lvType = (**TheGameHand).lvType;
  667.                                 STLoadLevel();
  668.                                 GameLoaded = 1;        
  669.                                 /* if a Doomsday level dont reset # of zaps */
  670.                                 if(ThisLevel.lvType ==4)
  671.                                     ThisLevel.plSuperZaps = (**TheGameHand).NumZaps;
  672.                                 Hero.lives = (**TheGameHand).lives;            
  673.                                 Hero.score = (**TheGameHand).score;            
  674.                                 Hero.drawscore = 1;        
  675.                                 Hero.freeLives = (**TheGameHand).freelives;            
  676.                                 Hero.Flags = (**TheGameHand).Flags;
  677.                                 ScoretoBeatIndex = 50;
  678.                                 ReleaseResource(TheGameHand);
  679.                                 Alert(501,0); 
  680.                             }
  681.                              break;
  682.                     }
  683.                 }
  684.             }
  685.         }
  686.     } while(ItemHit != EndPauseButton);
  687.     
  688.     HideCursor();
  689.     ShowWindow(BackdropWind);
  690.  
  691.     DisposDialog(PauseDialog);
  692.     ShowWindow(VA.window);
  693.     RectRgn(VA.window->visRgn,&VA.window->portRect);
  694.     SetPort(VA.window);
  695.  
  696.     VAEraseBuffer();
  697.     
  698.     if(cleanup != LevelSelectRunning)
  699.     {
  700.         VA.segmscale=(VA.frame.bottom>>6);            /* mz */
  701.         if(VA.segmscale<1) VA.segmscale=1;
  702.         k=VA.color;
  703.         VA.color=BG2;
  704.         VADrawNumber(ThisLevel.lvNumber,VA.frame.right/2-VA.segmscale-3,VA.segmscale*2+4);
  705.         VA.color=k;
  706.     }
  707.  
  708. The alerts just say that a game has been saved/loaded.
  709.  
  710. 19) Added next highest score on high score list to display in upper right corner.
  711. Modified GameLoop.c, GamePause.c, and STPlayer.c.
  712.  
  713. In GameLoop.c
  714.  
  715. #include "HighScoresToBeat.h"        /* mz */
  716.  
  717. extern    Initials    *HiScoresToBeat;
  718. extern    int         ScoretoBeatIndex;
  719.  
  720. void    GameLoop(Options)
  721. int        Options;
  722. {
  723.     int            i;
  724.     int            startLevel=0;        /* flag for starting level (mz) */
  725.     long int    levelStBonus=0;
  726.     long int    levelBonus=0;
  727.     int            levelComplete=0;
  728.     Handle        ScoreHand;
  729.         
  730.     /* read scores from resources  for top right corner */
  731.     if (PlayOptions->restart == 0)
  732.         ScoreHand=GetResource('SCOR',128);
  733.     else 
  734.         ScoreHand=GetResource('SCOR',129);
  735.     HLock(ScoreHand);
  736.     HiScoresToBeat = (Initials *)*ScoreHand;
  737.     ScoretoBeatIndex = 50;        /* start at the bottom */
  738.     
  739.     VAEraseBuffer();
  740.  
  741.     /*    Flush out some events and let MultiFinder update windows.    */
  742.     
  743. int GamePause.c
  744.  
  745. extern    int                ScoretoBeatIndex;    /* mz */
  746.  
  747. case LoadGame:
  748.                             {    GameRecHand    TheGameHand;
  749.                                 .
  750.                                 .
  751.                                 .
  752.                                 ScoretoBeatIndex = 50;
  753.                             }
  754. in STPlayer.c
  755.  
  756. #include "HighScoresToBeat.h"        /* mz */
  757.  
  758. extern    Initials    *HiScoresToBeat;
  759. extern    int         ScoretoBeatIndex;
  760.  
  761. void    IncreaseScore(points)
  762. long    points;
  763. {
  764.  
  765.     int            flashcount;
  766.                 
  767.     .
  768.     .
  769.     .
  770.     
  771.     
  772.     if (Hero.score > HiScoresToBeat[ScoretoBeatIndex].score)
  773.     {
  774.         unsigned char    *namestr=(void *)"YOU  ";
  775.         long    scoretobeat;
  776.         int        hsc=VA.color;
  777.         int        x;
  778.         
  779.         while ((Hero.score > HiScoresToBeat[ScoretoBeatIndex].score) && ScoretoBeatIndex>=1)
  780.             ScoretoBeatIndex--;
  781.         if (ScoretoBeatIndex < 1) /* player now has top score */
  782.         {    scoretobeat = Hero.score;
  783.             ScoretoBeatIndex = 1;
  784.         }
  785.         else
  786.         {    scoretobeat = HiScoresToBeat[ScoretoBeatIndex].score;
  787.             namestr = HiScoresToBeat[ScoretoBeatIndex].name; 
  788.         }
  789.         VA.color = BG2; 
  790.         if (ThisLevel.lvColor == 5)        /* check for invis lvl where BG2 is */
  791.             VA.color=BG1;                /* also invis. (mz)                 */
  792.         
  793.         VA.segmscale = Getfontscale();                    /* do initials         */
  794.         x = VA.frame.right - 2 - 5*(VA.segmscale + 7);
  795.         VAMoveTo(x,20);
  796.         VADrawText((char *) namestr,0,5);
  797.         
  798.         VA.segmscale=5;
  799.         x -= 2*(VA.segmscale + 7);                         /* sub for space    */
  800.         VADrawPadNumber(scoretobeat,x,20,8);
  801.         
  802.         VA.color = hsc;
  803.     }    /* end if */
  804. }
  805.  
  806. 20) on Doomsday levels (after 96) if the player dies, a new level (random) is selected.
  807. If the superap has been used, it does not get recharged until a full wave is cleared.
  808. To do this I modified STResource.c to include a lvType of 3.  This flag is set in
  809. GameLoop.c when the player dies and the lvType == 4.  Thus instead of the normal
  810. Redrawfield, a new level is loaded.
  811.  
  812. in STResource.c
  813.  
  814. case 3: /* case for death on doomsday levels, dont increment */
  815.         case 4: 
  816.             randGreenLevel = STARTGREEN + ((unsigned int)(Random()) % 16);
  817.             ThisLevel= **(LevelInfo **)GetResource('LEVL',randGreenLevel);
  818.             ThisLevel.lvNumber = highLvNum;
  819.             if (ThisLevel.lvType == 4)
  820.                 highLvNum++;
  821.             ThisLevel.lvType = 4;
  822.             break;
  823.  
  824. in GameLoop.c
  825.  
  826. in GameLoop(Options)
  827.  
  828.     int            DoomsdayDeath = 0;
  829.  
  830.  
  831.         if(Hero.state != HeroDead)
  832.         {    AddLife();
  833.             .
  834.             .
  835.             CreateFit();
  836.         }
  837.         else if(DoomsdayDeath)
  838.         {
  839.             int    numzaps=ThisLevel.plSuperZaps;
  840.             
  841.             ThisLevel.lvType = 3;                /* set flag for Dommsday death         */
  842.             STLoadLevel(); 
  843.             ThisLevel.plSuperZaps = numzaps;    /* Keep old # of zaps                 */
  844.             Hero.Flags &= (FLAGSMASK - 0x0020);    /* unset re-zap msg                    */
  845.             CreateFit();
  846.             Hero.Flags &= 0x0020;                /* set show re-zap msg                 */
  847.             DoomsdayDeath = 0;
  848.         }
  849.         else
  850.         {    VA.color=0;
  851.             RedrawField();
  852.         }
  853.         .
  854.         .
  855.         } while(Hero.state != HeroDead && Hero.state != HeroFlying);
  856.  
  857.         if(Hero.state == HeroFlying)
  858.             STFlyThruLoop(Options);
  859.             
  860.         if(ThisLevel.lvType == 4 && Hero.lives>0) /* player has died in Doomsday level */
  861.         {    DoomsdayDeath = 1;
  862.             VA.color=-1;        /*    Black                    */
  863.             RedrawField();
  864.             RedrawSpikes();
  865.         }
  866.     
  867.     } while(Hero.lives>0 || Hero.state != HeroDead);
  868.     
  869.  
  870. 21) Changed the floating scores so they would not be called if a superzap was used.
  871. In STFuseball.c I changed each of the 3 calls in UpdateFuseballs() to
  872.  
  873.                             if(PlayOptions->showfscores && zap != -2)
  874.                                 AddFLScore(x,y,ThisLevel.fuBullseye*1.5);
  875. and added the variable (int) zap and inserted it into the shothittest
  876.  
  877.             if(zap=ShotHitTest(fbp->lane,l))
  878.             
  879. A -2 is returned if a superzap is used.
  880. From STShot.c
  881.  
  882. if(Hero.superzapping)
  883.     {    if(Hero.superzapping==2)    /*    Single enemy zap.    */
  884.             Hero.superzapping=0;
  885.         return -2;                    /* mz */
  886.     }
  887.     
  888. 22) Whoa found a stupid bug from version 1.0.  I think adding EvenBetterBusError
  889. allowed me to catch it.  Was using CLOT's that did not exist for the free life flash
  890.  
  891. if ((!(Hero.NewLifeColorInvert)) || (Hero.NewLifeColorInvert==12)) 
  892.         {
  893.             ZapColorsHandle=GetResource('CLOT',ThisLevel.lvColor);
  894.             Hero.NewLifeColorInvert=0;
  895.         }
  896.         else{ /* run through all colors to enhance flash (mz) */
  897.             ZapColorsHandle=GetResource('CLOT',(Hero.NewLifeColorInvert % 6 + 1));
  898.             Hero.NewLifeColorInvert++;
  899.         }
  900.         
  901. 23) Set a max of 5 free lives (plus active life).  Added a const to STPlayer.c and
  902. an additional if statement to IncreaseScore()
  903.  
  904. #define MAXLIVES        (5) /* (mz) */
  905.  
  906.     if (Hero.score > Hero.freeLives)         /* check for free life (mz)     */
  907.     {    
  908.         if(Hero.lives < MAXLIVES || (Hero.lives <= MAXLIVES && Hero.state==HeroFlying))    
  909.                                             /* no more than MAXLIVES lives     */
  910.         {
  911.             PlayB(ZZFreeLife,999);          /* play free life sound (mz)     */
  912.             if((!PlayOptions->noLoudSounds)&&(Hero.state!=HeroFlying))
  913.                 PlayA(ZZFreeLife,999);
  914.             Hero.NewLifeColorInvert=1;             /* set flash flag (mz)         */
  915.             AddLife();
  916.         }
  917.         Hero.freeLives = Hero.score - (Hero.score % freeLifeScore) + freeLifeScore;
  918.         /* round score up to next interval */
  919.     }
  920.     
  921. 24) Added "Superzapper Recharge" message to fly-in routine.  It should not happen on the
  922. first level, and should not happen on Doomsday levels until a level has been cleared.
  923.  
  924. Mods were to Gridtest.c
  925.  
  926. extern    Player    Hero;
  927.  
  928. void DoZapRecharge(onoff)
  929. int onoff;
  930. {
  931.     /* This next section will add the message             */
  932.     /* "Superzapper recharge" to the screen (mz)        */
  933.     
  934.     unsigned char    *text=(void *)"\pSuperzapper Recharge";
  935.     int                x,y;
  936.     
  937.     if(Hero.Flags & 0x0020)
  938.     {
  939.         VA.segmscale = (int)(Getfontscale() * 1.5);
  940.         if(VA.segmscale <=1) 
  941.             VA.segmscale=2;
  942.         x = (int)( (VA.frame.right - 20*(VA.segmscale*3 + 3))/2 );
  943.         y = (int)(VA.frame.bottom - 2);
  944.         VAMoveTo(x,y);
  945.         VA.color=BG1;
  946.         if (!onoff)                    /* Erase option */
  947.             VA.color = -1;        
  948.         VADrawText((char *)text,1,20);
  949.     }
  950. }
  951.  
  952. in CreateFit()
  953.  
  954. .
  955. .
  956. .
  957.     VADrawNumber(ThisLevel.lvNumber,VA.frame.right/2-VA.segmscale-3,VA.segmscale*2+4);
  958.     VA.color=k;
  959.         
  960.     DoZapRecharge(1);                /* (mz) */
  961.         
  962.     spacehand=(void *)GetResource('SPCE',ThisLevel.lvField);
  963. .
  964. .
  965. .
  966.     for(j=0;j<ANGLES;j++)
  967.         if(LaneSel[0][j]==-1)
  968.             LaneSel[0][j]=space->numsegs-1;
  969.  
  970.     StarStep();
  971.  
  972.     DoZapRecharge(0);                /* (mz) */
  973.     
  974.     for(j=k;j<k+ANGLES/2;j++)
  975.         LaneSel[space->numsegs][j % ANGLES]=0;
  976.  
  977.     StarStep();
  978.  
  979. 25) I found a bug in my dealing with the starting level.  A saved game at startup
  980. would deal with finishing the level saved as if it was the first level in the game,
  981. and give the lvStBonus.  I also found it useful to have this info available with the
  982. Superzap msg (#24), so I added a field to the Hero struct (sorry).  I updated older
  983. things to use the new info.  To make the mode of the new variable I am using the
  984. bit positions as flag.  As a bonus, of sorts, I could remove the NewLifeColorInvert
  985. from the struct and use part of the Flags for that.
  986.  
  987. in Storm.h Player struct.
  988. int        Flags;         /* set of flags checked by bit position (mz)     */
  989.                         /* use by ORing and ANDing with Flags (mz)        */
  990.                         /* 1-  Used to store CLOT # for flashing screen */
  991.                         /* 2-     "                                        */
  992.                         /* 4-     "                                        */
  993.                         /* 8-   "                                        */
  994.                         /* 16- flag for if first level done (mz)        */
  995.                         /* 32- flag for show ZapMsg    (mz)                */
  996.                         /* 64-  unused*/
  997.                         /* 128-  etc */
  998. }    Player;
  999.  
  1000.  
  1001. in GameLoop.c,
  1002.  
  1003. - remove the startgame variable
  1004. - change things to as follows....
  1005.  
  1006. in GameLoop(),
  1007. update test to set flags after first wave completed
  1008. .
  1009. .
  1010. .
  1011.         if (levelComplete == 1)
  1012.             {
  1013.                 /* check to see if starting level not finished (mz)                 */
  1014.                 if (!(Hero.Flags & 0x0010))
  1015.                 {
  1016.                     (Hero.Flags) |= 0x0030; /* set start bonus granted and show zap */
  1017.                     IncreaseScore(levelStBonus); /* give starting bonus                */
  1018.                 } 
  1019.                 IncreaseScore(levelBonus);
  1020.                 DisplayScore();            
  1021.             }
  1022. .
  1023. .
  1024. .remove redundant tests that were here
  1025.  
  1026.         if(Hero.state == HeroPlaying)
  1027.             {    if(ThisLevel.edgeCount==ThisLevel.totalCount)
  1028.                 {    Hero.endtimer--;
  1029.                     if(Hero.endtimer<=0)
  1030.                     {    Hero.state=HeroFlying;
  1031.                         Hero.flydepth=0;
  1032.                         levelComplete=1;
  1033.                         levelStBonus=ThisLevel.lvStBonus;
  1034.                         levelBonus=ThisLevel.lvBonus;
  1035.                     }
  1036.                 }
  1037.             }
  1038. in STPlayer.c 
  1039.  
  1040. -add an init statetment to ZeroScore()
  1041.     Hero.Flags = 0;    /* init new game flag */            
  1042. -update the flash flag to use the new Flags in IncreaseScore()
  1043.             Hero.Flags |= 0x0001;             /* set flash flag (mz)         */
  1044.             AddLife();
  1045. -update part where I put "flash"
  1046.     /* if lower 4 bits !=0 then colors are being flashed.  Counts up to 12    */
  1047.     /* so it cycles thru the CLOT's twice modulo 6, then reset to 0. (mz)    */
  1048.         
  1049.     if((Hero.superzapping==1 || Hero.Flags & 0x000F) && Hero.state != HeroFlying) 
  1050.     {    
  1051.         if ( (!(Hero.Flags & 0x000F)) || (Hero.Flags & 0x000C)==0x000C ) 
  1052.         {
  1053.             /* flashing is done    */
  1054.             ZapColorsHandle=GetResource('CLOT',ThisLevel.lvColor);
  1055.             Hero.Flags &= 0xFFF0;
  1056.         }
  1057.         else{ /* run through all colors to enhance flash (mz) */
  1058.             ZapColorsHandle=GetResource('CLOT',((Hero.Flags & 0x000F) % 6 + 1));
  1059.             Hero.Flags++;
  1060.         }
  1061.         VASetColors(ZapColorsHandle);
  1062.         ReleaseResource(ZapColorsHandle);
  1063.     }    
  1064.  
  1065.  
  1066.             
  1067. 26) Changed Fuseball behavior.  According to the Tempest gods, the fuseballs should
  1068. not stay on the edge until all other things are dead, so I changed the edge test in
  1069. STFuseballs.c
  1070.  
  1071.                 case Brownian:
  1072.                         fbp->level += fbp->levelspeed;
  1073.                         if(fbp->level>(DEPTH<<4))
  1074.                         {    fbp->level= (DEPTH<<4);
  1075.                             if(fbp->levelspeed>0)
  1076.                             {    fbp->levelspeed= - (fbp->levelspeed>>1);
  1077.                             }
  1078.                         }
  1079.                         else
  1080.                         if(fbp->level<=0)
  1081.                         {    fbp->level=0;
  1082.                             fbp->levelspeed=0;
  1083.                             if (ThisLevel.fuCount == ThisLevel.totalCount;)
  1084.                                 fbp->mode=Edge; /* only have fuseballs on edge     */
  1085.                                                 /*    after all else dead (mz)    */
  1086.                                                 
  1087. 27) Changed extra life sound and flash related to clearing first level and 
  1088. starting bonus.  Should not happen on first level cleared.
  1089.  
  1090.             if(Hero.Flags & 0x0010)
  1091.             {
  1092.                 PlayB(ZZFreeLife,999);        /* play free life sound (mz)     */
  1093.                 if((!PlayOptions->noLoudSounds)&&(Hero.state!=HeroFlying))
  1094.                     PlayA(ZZFreeLife,999);
  1095.                 Hero.Flags |= 0x0001;         /* set flash flag (mz)         */
  1096.             }
  1097.             AddLife();
  1098.             
  1099. 28) Another fix to GamePause so level number would not be drawn during TitlesRunning.
  1100. in GamePause.c
  1101.  
  1102. if((cleanup != LevelSelectRunning) && (cleanup != TitlesRunning))
  1103.  
  1104.  
  1105. 29) Changed Levelselect to include saved game.  Added extra save game so each
  1106. play mode has game save.
  1107.  
  1108. This involved basically rewriting the 
  1109. int        CreateStable(stable,highestLastLevel)
  1110. function.  The available levels for enrty into the table are stored in an array.
  1111.  
  1112. A flag check was also added to the end of the fcn DoLevelSelect(highestLastLevel)
  1113. with 
  1114.     if(levelnum == 0)            /* saved game was loaded as level select */
  1115.         Hero.Flags |= SavedGameStartMask;
  1116.  
  1117. At this same time, I moved all Hero.Flags stuff into the file heroflags.h
  1118. and replaced all hard-coded bit operands with Mask names stored in this file.
  1119.  
  1120. 30) Another attempt to fix the occassional errant zoomer box on the high scores.
  1121.  
  1122. in DrawZoomer() add a second condition for MainStage == 15
  1123.  
  1124.         InitZoomRect(&Zoom);
  1125.         if(MainStage == 14 || MainStage == 15){